pub mod input_t {
    use yew::prelude::*;
    // check the input char available
    fn check_in_legal(s: u32) -> bool {
        if s >= 48 && s <= 57 {
            true
        } else if s >= 65 && s <= 90 {
            true
        } else if s == 20 && s == 32 {
            true
        } else {
            false
        }
    }

    // if available then change to a standard format
    fn change_word_case(s: u32, c: bool) -> u32 {
        if s >= 65 && s <= 90 {
            if c {
                s
            } else {
                s + 32
            }         
        } else {
            s
        }

    }

    #[derive(Clone, PartialEq, Properties)]
    pub struct InputPros {
        // for char vector
        pub val: String,
    }

    impl InputPros {
        fn new(val: &str) -> InputPros {
            InputPros { val: val.to_owned() }
        }

        fn change(&mut self, s: u32, state: bool) -> bool {
            let s = change_word_case(s, state);
            // change s: u32 -> char
            // push into val: String
            self.val.push(s.try_into().unwrap());
            false
        }

        // delete the backspace
        fn backspace(&mut self) -> bool {
            let len = self.val.len();
            if len == 0 { false }
            else { 
                self.val = self.val[..self.val.len() - 1].to_owned();
                false 
            }
        }
    }

    pub struct InputT {
        props: InputPros,
    }

    pub enum Message {
        Enter, // Enter press
        Change(u32, bool), // push u32 to val: String
        Backspace, // 
        Nil, // Nothings
    }

    impl Component for InputT {
        type Message = Message;

        type Properties = InputPros;

        fn create(_ctx: &Context<Self>) -> Self {
            Self { props: InputPros::new("") }
        }

        fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
            match msg {
                // available char => add char
                Message::Change(s, b) => self.props.change(s, b),
                // Enter -> render
                Message::Enter => true,
                // Backspace -> delete backspace
                Message::Backspace => self.props.backspace(),
                Message::Nil => false,
            }
        }


        fn view(&self, ctx: &Context<Self>) -> Html {
            let link = ctx.link();

            html! {
                <div>
                    <input 
                        type="text" 
                        id="test_input" 
                        onkeydown={
                            link.callback(|e: KeyboardEvent| {
                                let key_code = e.key_code();
                                if key_code == 13 {
                                // 13 CR Enter key
                                    Message::Enter
                                } else if key_code == 8 {
                                // 8 BS Backspace key
                                    Message::Backspace
                                } else if check_in_legal(key_code) {
                                // available to add 
                                    Message::Change(key_code, e.get_modifier_state("CapsLock"))
                                } else {
                                // illegal
                                    Message::Nil
                                }
                            })
                        }
                    />
                    // show the val: String
                    <p>{ self.props.val.clone() }</p>
                </div>
            }
        }
    }
}